using System;
using System.IO;
using System.Net;
using CodePlex.TfsLibrary.RegistrationWebSvc;
using CodePlex.TfsLibrary.RepositoryWebSvc;
using CodePlex.TfsLibrary.Utility;
using CodePlex.UnitTestUtility;
using Xunit;

namespace CodePlex.TfsLibrary.ObjectModel
{
    public class SourceControlServiceTest
    {
        public class AddMappingToWorkspace
        {
            [Fact]
            public void AddsFullyQualifiedPath()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                NetworkCredential creds = new NetworkCredential("joe", "bob");

                service.AddWorkspaceMapping("http://tfsUrl", creds, "foobar", "$/Foo", ".");

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                WorkingFolder folder =
                    service.RepositoryWebSvc.UpdateWorkspace_UpdatedWorkspace.Folders[
                        service.RepositoryWebSvc.UpdateWorkspace_UpdatedWorkspace.Folders.Length - 1];
                Assert.Equal(Directory.GetCurrentDirectory(), folder.local);
            }

            [Fact]
            public void CallsRepositoryWebService()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                NetworkCredential creds = new NetworkCredential("joe", "bob");
                int oldFolderCount = service.RepositoryWebSvc.UpdateWorkspace_OriginalWorkspace.Folders.Length;
                string originalName = service.RepositoryWebSvc.UpdateWorkspace_OriginalWorkspace.name;

                service.AddWorkspaceMapping("http://tfsUrl", creds, "foobar", "$/Foo", @"C:\Bar");

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Equal("foobar", service.RepositoryWebSvc.QueryWorkspace_WorkspaceName);
                Assert.Equal("joe", service.RepositoryWebSvc.QueryWorkspace_Owner);

                Assert.Equal(originalName, service.RepositoryWebSvc.UpdateWorkspace_OldWorkspaceName);
                Assert.Equal("joe", service.RepositoryWebSvc.UpdateWorkspace_Owner);
                Assert.Equal(service.RepositoryWebSvc.UpdateWorkspace_OriginalWorkspace.name,
                             service.RepositoryWebSvc.UpdateWorkspace_UpdatedWorkspace.name);
                Assert.Equal(service.RepositoryWebSvc.UpdateWorkspace_OriginalWorkspace.Comment,
                             service.RepositoryWebSvc.UpdateWorkspace_UpdatedWorkspace.Comment);
                Assert.Equal(service.RepositoryWebSvc.UpdateWorkspace_OriginalWorkspace.computer,
                             service.RepositoryWebSvc.UpdateWorkspace_UpdatedWorkspace.computer);
                Assert.Equal(service.RepositoryWebSvc.UpdateWorkspace_OriginalWorkspace.owner,
                             service.RepositoryWebSvc.UpdateWorkspace_UpdatedWorkspace.owner);
                Assert.Equal(oldFolderCount + 1,
                             service.RepositoryWebSvc.UpdateWorkspace_UpdatedWorkspace.Folders.Length);
                WorkingFolder folder =
                    service.RepositoryWebSvc.UpdateWorkspace_UpdatedWorkspace.Folders[
                        service.RepositoryWebSvc.UpdateWorkspace_UpdatedWorkspace.Folders.Length - 1];
                Assert.Equal("$/Foo", folder.item);
                Assert.Equal(@"C:\Bar", folder.local);
                Assert.Equal(WorkingFolderType.Map, folder.type);
            }
        }

        public class Commit
        {
            [Fact]
            public void CallsWebService()
            {
                NetworkCredential creds = new NetworkCredential("joe", "bob");
                TestableSourceControlService service = TestableSourceControlService.Create();

                int result =
                    service.Commit("http://tfsUrl", creds, "workspace", "comment", new string[] { "$/Foo", "$/Foo/Bar" });

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Equal("workspace", service.RepositoryWebSvc.CheckIn_WorkspaceName);
                Assert.Equal("joe", service.RepositoryWebSvc.CheckIn_OwnerName);
                Assert.Equal(2, service.RepositoryWebSvc.CheckIn_ServerItems.Count);
                Assert.Contains("$/Foo", service.RepositoryWebSvc.CheckIn_ServerItems);
                Assert.Contains("$/Foo/Bar", service.RepositoryWebSvc.CheckIn_ServerItems);
                Assert.Equal("joe", service.RepositoryWebSvc.CheckIn_Info.owner);
                Assert.Equal("comment", service.RepositoryWebSvc.CheckIn_Info.Comment);
                Assert.Equal(CheckinOptions.ValidateCheckinOwner, service.RepositoryWebSvc.CheckIn_CheckinOptions);
                Assert.Equal(service.RepositoryWebSvc.CheckIn_Result.cset, result);
            }

            [Fact]
            public void FailuresThrow()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                service.RepositoryWebSvc.CheckIn_Failures.Add(new Failure(@"C:\Foo\Bar", "Forced failure"));

                Assert.Throws<TfsFailureException>(delegate
                                                   {
                                                       service.Commit(null, null, null, null, new string[0]);
                                                   });
            }
        }

        public class CreateWorkspace
        {
            [Fact]
            public void CallsRepositoryWebService()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                NetworkCredential creds = new NetworkCredential("joe", "bob");

                service.CreateWorkspace("http://tfsUrl", creds, "foobar", "this is my comment");

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Equal("foobar", service.RepositoryWebSvc.CreateWorkspace_Workspace.name);
                Assert.Equal("this is my comment", service.RepositoryWebSvc.CreateWorkspace_Workspace.Comment);
                Assert.Equal("joe", service.RepositoryWebSvc.CreateWorkspace_Workspace.owner);
            }

            [Fact]
            public void ConvertsTFSAccessDeniedExceptionToNetworkAccessDeniedException()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                service.Factory.mock.CreateWorkspace_Throw = new Exception("TF14044:");

                Assert.Throws<NetworkAccessDeniedException>(
                    delegate
                    {
                        service.CreateWorkspace("http://tfsUrl", null, "foobar", "this is my comment");
                    });
            }
        }

        public class DeleteWorkspace
        {
            [Fact]
            public void CallsRepositoryWebService()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                NetworkCredential creds = new NetworkCredential("joe", "bob");

                service.DeleteWorkspace("http://tfsUrl", creds, "workspace");

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Equal("workspace", service.RepositoryWebSvc.DeleteWorkspace_WorkspaceName);
                Assert.Equal("joe", service.RepositoryWebSvc.DeleteWorkspace_Owner);
            }
        }

        public class GetLatestChangeset
        {
            [Fact]
            public void CallsRepositoryWebService()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                NetworkCredential creds = new NetworkCredential("joe", "bob");

                int result = service.GetLatestChangeset("http://tfsUrl", creds);

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Equal(result, service.RepositoryWebSvc.GetRepositoryProperties__Result.lcset);
            }
        }

        public class GetWorkspaces
        {
            [Fact]
            public void CallsRepositoryWebService()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                NetworkCredential creds = new NetworkCredential("joe", "bob");

                WorkspaceInfo[] results = service.GetWorkspaces("http://tfsUrl", creds, WorkspaceComputers.AllComputers);

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Null(service.RepositoryWebSvc.QueryWorkspaces_Computer);
                Assert.Equal("joe", service.RepositoryWebSvc.QueryWorkspaces_Owner);
                Assert.Equal(service.RepositoryWebSvc.QueryWorkspaces_Result.Length, results.Length);

                for (int idx = 0; idx < results.Length; ++idx)
                    Assert.Equal(service.RepositoryWebSvc.QueryWorkspaces_Result[idx].name, results[idx].Name);
            }

            [Fact]
            public void CanFilterOnlyForLocalMachineWorkspaces()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                service.RepositoryWebSvc.QueryWorkspaces_Result = new Workspace[]
                    {
                        new Workspace("workspace1", Guid.NewGuid().ToString(), "ownername", "comment"),
                        new Workspace("workspace2", Environment.MachineName, "ownername2", "comment 2")
                    };

                NetworkCredential creds = new NetworkCredential("joe", "bob");

                WorkspaceInfo[] results = service.GetWorkspaces("http://tfsUrl", creds, WorkspaceComputers.ThisComputer);

                Assert.Equal(1, results.Length);
                Assert.Equal("workspace2", results[0].Name);
            }
        }

        public class PendChanges
        {
            [Fact]
            public void CallsRepositoryWebService()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                NetworkCredential creds = new NetworkCredential("billy", "ray");
                PendRequest[] requests = new PendRequest[] { PendRequest.AddFile("file", 1) };

                service.PendChanges("http://tfsUrl", creds, "workspace", requests);

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Equal("workspace", service.RepositoryWebSvc.PendChanges_WorkspaceName);
                Assert.Equal("billy", service.RepositoryWebSvc.PendChanges_OwnerName);
                Assert.Equal(1, service.RepositoryWebSvc.PendChanges_Changes.Length);
                Assert.Equal("file", service.RepositoryWebSvc.PendChanges_Changes[0].item.item);
                Assert.Equal(RequestType.Add, service.RepositoryWebSvc.PendChanges_Changes[0].req);
                Assert.Equal(ItemType.File, service.RepositoryWebSvc.PendChanges_Changes[0].type);
                Assert.Equal(1, service.RepositoryWebSvc.PendChanges_Changes[0].enc);
            }

            [Fact]
            public void FailureThrows()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                service.RepositoryWebSvc.PendChanges_Failures = new Failure[] { new Failure() };

                Assert.Throws<TfsFailureException>(delegate
                                                   {
                                                       service.PendChanges("http://tfsUrl", null, "workspace", new PendRequest[] { PendRequest.AddFile("foo", 12) });
                                                   });
            }
        }

        public class QueryItems
        {
            [Fact]
            public void CallsRepositoryWebService()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                NetworkCredential creds = new NetworkCredential("joe", "bob");

                service.QueryItems("http://tfsUrl", creds, "serverPath", RecursionType.Full, VersionSpec.Latest,
                                   DeletedState.Any, ItemType.Any);

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Null(service.RepositoryWebSvc.QueryItems_WorkspaceName);
                Assert.Null(service.RepositoryWebSvc.QueryItems_Owner);
                Assert.Equal<VersionSpec>(VersionSpec.Latest, service.RepositoryWebSvc.QueryItems_Version);
                Assert.Equal(DeletedState.Any, service.RepositoryWebSvc.QueryItems_DeletedState);
                Assert.Equal(ItemType.Any, service.RepositoryWebSvc.QueryItems_ItemType);
                Assert.Equal(1, service.RepositoryWebSvc.QueryItems_Items.Length);
                Assert.Equal("serverPath", service.RepositoryWebSvc.QueryItems_Items[0].item);
                Assert.Equal(RecursionType.Full, service.RepositoryWebSvc.QueryItems_Items[0].recurse);
                Assert.True(service.RepositoryWebSvc.QueryItems_GenerateDownloadUrls);
            }

            [Fact]
            public void QueryItemsUsingIdsCallsRepositoryWebService()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                NetworkCredential creds = new NetworkCredential("joe", "bob");

                service.QueryItems("http://tfsUrl", creds, new int[] { 123 }, 456);

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Equal(123, service.RepositoryWebSvc.QueryItemsById_ItemIds[0]);
                Assert.Equal(456, service.RepositoryWebSvc.QueryItemsById_ChangeSet);
                Assert.Equal(false, service.RepositoryWebSvc.QueryItemsById_GenerateDownloadUrls);
            }

            [Fact]
            public void ZeroElementsFromQueryItemsCallsQueryHistoryThenThrows()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                ItemSet itemSet = new ItemSet();
                itemSet.Items = new Item[0];
                service.RepositoryWebSvc.QueryItems_Result = new ItemSet[] { itemSet };

                Assert.Throws<NetworkAccessDeniedException>(
                    delegate
                    {
                        service.QueryItems("http://tfsUrl", null, "serverPath", RecursionType.Full, VersionSpec.Latest, DeletedState.Any, ItemType.Any);
                    });

                Assert.Null(service.RepositoryWebSvc.QueryHistory_WorkspaceName);
                Assert.Null(service.RepositoryWebSvc.QueryHistory_WorkspaceOwner);
                Assert.Equal("serverPath", service.RepositoryWebSvc.QueryHistory_ItemSpec.item);
                Assert.Equal(RecursionType.None, service.RepositoryWebSvc.QueryHistory_ItemSpec.recurse);
                Assert.Equal<VersionSpec>(VersionSpec.Latest, service.RepositoryWebSvc.QueryHistory_VersionItem);
                Assert.Null(service.RepositoryWebSvc.QueryHistory_User);
                Assert.Equal<VersionSpec>(VersionSpec.Latest, service.RepositoryWebSvc.QueryHistory_VersionFrom);
                Assert.Equal<VersionSpec>(VersionSpec.Latest, service.RepositoryWebSvc.QueryHistory_VersionTo);
                Assert.Equal(1, service.RepositoryWebSvc.QueryHistory_MaxCount);
                Assert.False(service.RepositoryWebSvc.QueryHistory_IncludeFiles);
                Assert.False(service.RepositoryWebSvc.QueryHistory_GenerateDownloadUrls);
                Assert.False(service.RepositoryWebSvc.QueryHistory_SlotMode);
            }
        }

        public class QueryLog
        {
            [Fact]
            public void CallsRepositoryWebService()
            {
                NetworkCredential creds = new NetworkCredential();
                TestableSourceControlService service = TestableSourceControlService.Create();

                service.QueryLog("http://tfsUrl", creds, "$/Foo/bar.txt", VersionSpec.First, VersionSpec.Latest, RecursionType.Full, 256);

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Null(service.RepositoryWebSvc.QueryHistory_WorkspaceName);
                Assert.Null(service.RepositoryWebSvc.QueryHistory_WorkspaceOwner);
                Assert.Equal("$/Foo/bar.txt", service.RepositoryWebSvc.QueryHistory_ItemSpec.item);
                Assert.Equal(RecursionType.Full, service.RepositoryWebSvc.QueryHistory_ItemSpec.recurse);
                Assert.Equal<VersionSpec>(VersionSpec.Latest, service.RepositoryWebSvc.QueryHistory_VersionItem);
                Assert.Null(service.RepositoryWebSvc.QueryHistory_User);
                Assert.Equal<VersionSpec>(VersionSpec.First, service.RepositoryWebSvc.QueryHistory_VersionFrom);
                Assert.Equal<VersionSpec>(VersionSpec.Latest, service.RepositoryWebSvc.QueryHistory_VersionTo);
                Assert.Equal(256, service.RepositoryWebSvc.QueryHistory_MaxCount);
                Assert.True(service.RepositoryWebSvc.QueryHistory_IncludeFiles);
                Assert.False(service.RepositoryWebSvc.QueryHistory_GenerateDownloadUrls);
                Assert.False(service.RepositoryWebSvc.QueryHistory_SlotMode);
            }

            [Fact]
            public void TransformsResults()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();

                LogItem item =
                    service.QueryLog("http://tfsUrl", null, "$/Foo/bar.txt", VersionSpec.First, VersionSpec.Latest, RecursionType.None, 256);

                Assert.Equal("$/Foo/bar.txt", item.ServerPath);
                Assert.Equal(service.RepositoryWebSvc.QueryHistory_Result.Length, item.History.Length);

                for (int idx = 0; idx < item.History.Length; idx++)
                {
                    Assert.Equal(service.RepositoryWebSvc.QueryHistory_Result[0].Changes[0].Item.cs,
                                 item.History[idx].ChangeSetID);
                    Assert.Equal(service.RepositoryWebSvc.QueryHistory_Result[0].Comment, item.History[idx].Comment);
                    Assert.Equal(service.RepositoryWebSvc.QueryHistory_Result[0].date, item.History[idx].CommitDateTime);
                    Assert.Equal(service.RepositoryWebSvc.QueryHistory_Result[0].cmtr, item.History[idx].Username);
                }
            }
        }

        public class UndoPendingChanges
        {
            [Fact]
            public void CallsRepositoryWebService()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                NetworkCredential creds = new NetworkCredential("billy", "ray");
                string[] serverItems = new string[] { "file" };

                service.UndoPendingChanges("http://tfsUrl", creds, "workspace", serverItems);

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Equal("workspace", service.RepositoryWebSvc.UndoPendingChanges_WorkspaceName);
                Assert.Equal("billy", service.RepositoryWebSvc.UndoPendingChanges_OwnerName);
                Assert.Equal(1, service.RepositoryWebSvc.UndoPendingChanges_Items.Length);
                Assert.Equal("file", service.RepositoryWebSvc.UndoPendingChanges_Items[0].item);
            }

            [Fact]
            public void FailureThrows()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                service.RepositoryWebSvc.UndoPendingChanges_Failures = new Failure[] { new Failure() };

                Assert.Throws<TfsFailureException>(delegate
                                                   {
                                                       service.UndoPendingChanges("http://tfsUrl", null, "workspace", new string[] { "file" });
                                                   });
            }
        }

        public class UpdateLocalVersions
        {
            [Fact]
            public void CallsRepositoryWebService()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                NetworkCredential creds = new NetworkCredential("joe", "bob");
                LocalUpdate[] updates = new LocalUpdate[1] { LocalUpdate.FromLocal(2, "target", 3) };

                service.UpdateLocalVersions("http://tfsUrl", creds, "workspaceName", updates);

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
                Assert.Equal(TfsUtil.GetUsername(creds, "http://tfsUrl"),
                             service.RepositoryWebSvc.UpdateLocalVersion_OwnerName);
                Assert.Equal("workspaceName", service.RepositoryWebSvc.UpdateLocalVersion_WorkspaceName);
                Assert.Equal(1, service.RepositoryWebSvc.UpdateLocalVersion_Updates.Length);
                Assert.Equal("target", service.RepositoryWebSvc.UpdateLocalVersion_Updates[0].tlocal);
                Assert.Equal(2, service.RepositoryWebSvc.UpdateLocalVersion_Updates[0].itemid);
                Assert.Equal(3, service.RepositoryWebSvc.UpdateLocalVersion_Updates[0].lver);
            }
        }

        public class UploadFile
        {
            [Fact]
            public void TheTest()
            {
                NetworkCredential creds = new NetworkCredential("joe", "bob");
                TestableSourceControlService service = TestableSourceControlService.Create();
                service.FileSystem.WriteAllText(@"C:\Foo\bar.txt", "Foo bar");

                service.UploadFile("http://tfsUrl", creds, "workspace", @"C:\Foo\bar.txt", "$/Foo/bar.txt");

                Assert.Equal("http://tfsUrl", service.RegistrationService.TfsUrl);
                Assert.Same(creds, service.RegistrationService.Credentials);
                Assert.Equal(StubRegistrationService.UploadUrl, service.WebTransferService.PostForm_Url);
                Assert.Same(creds, service.WebTransferService.PostForm_Credentials);
            }
        }

        public class QueryBranches
        {
            [Fact]
            public void QueriesCorrectServerWithCorrectCreds()
            {
                var creds = new NetworkCredential("joe", "bob");
                TestableSourceControlService service = TestableSourceControlService.Create();
                service.RepositoryWebSvc.QueryBranches_Result = new[] {new BranchRelative[0]};

                service.QueryBranches("http://tfsUrl", creds, null, null);

                Assert.Equal("http://tfsUrl", service.Factory.TfsUrl);
                Assert.Same(creds, service.Factory.Credentials);
            }

            [Fact]
            public void QueriesAllWorkspaces()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                service.RepositoryWebSvc.QueryBranches_Result = new[] {new BranchRelative[0]};

                service.QueryBranches(null, null, null, null);

                Assert.Null(service.RepositoryWebSvc.QueryBranches_WorkspaceName);
                Assert.Null(service.RepositoryWebSvc.QueryBranches_WorkspaceOwner);
            }

            [Fact]
            public void QueriesCorrectItemsAndVersion()
            {
                TestableSourceControlService service = TestableSourceControlService.Create();
                service.RepositoryWebSvc.QueryBranches_Result = new[] {new BranchRelative[0]};
                var items = new[] { new ItemSpec() };
                var version = new ChangesetVersionSpec();

                service.QueryBranches(null, null, items, version);

                Assert.Equal(items, service.RepositoryWebSvc.QueryBranches_Items);
                Assert.Equal(version, service.RepositoryWebSvc.QueryBranches_Version);
            }

            [Fact]
            public void ReturnsBranchItems()
            {
                var service = TestableSourceControlService.Create();
                service.RepositoryWebSvc.QueryBranches_Result = new[]
                {
                   new[]
                   {
                       new BranchRelative { BranchFromItem = new Item { itemid = 4 }, BranchToItem = new Item { itemid = 3 }},
                       new BranchRelative { BranchFromItem = new Item { itemid = 1 }, BranchToItem = new Item { itemid = 2 }}
                   },
                   new[]
                   {
                       new BranchRelative { BranchToItem = new Item { itemid = 50 }}
                   }
                };
                var result = service.QueryBranches(null, null, null, null);

                Assert.Equal(2, result.Length);
                Assert.Equal(2, result[0].Length);
                Assert.Equal(4, result[0][0].FromItem.ItemId);
                Assert.Equal(3, result[0][0].ToItem.ItemId);
                Assert.Equal(1, result[0][1].FromItem.ItemId);
                Assert.Equal(1, result[1].Length);
                Assert.Null(result[1][0].FromItem);
                Assert.Equal(50, result[1][0].ToItem.ItemId);
            }
        }

        class TestableSourceControlService : SourceControlService
        {
            public readonly Factory Factory;
            public readonly MockFileSystem FileSystem;
            public readonly StubRegistrationService RegistrationService;
            public readonly StubWebTransferService WebTransferService;

            TestableSourceControlService(StubRegistrationService registrationSvc,
                                         Factory factory,
                                         StubWebTransferService webTransferSvc,
                                         MockFileSystem fileSystem)
                : base(registrationSvc, factory, webTransferSvc, fileSystem)
            {
                RegistrationService = registrationSvc;
                Factory = factory;
                WebTransferService = webTransferSvc;
                FileSystem = fileSystem;
            }

            public StubRepositoryWebSvc RepositoryWebSvc
            {
                get { return Factory.mock; }
            }

            public static TestableSourceControlService Create()
            {
                MockFileSystem fileSystem = new MockFileSystem();

                return new TestableSourceControlService(new StubRegistrationService(), new Factory(),
                                                        new StubWebTransferService(fileSystem), fileSystem);
            }
        }
    }

    class Factory : IRepositoryWebSvcFactory
    {
        public ICredentials Credentials;
        public StubRepositoryWebSvc mock = new StubRepositoryWebSvc();
        public string TfsUrl;

        public IRepositoryWebSvc Create(string tfsUrl,
                                        ICredentials credentials)
        {
            TfsUrl = tfsUrl;
            Credentials = credentials;
            return mock;
        }
    }
}